﻿#include "CUartSendModule.h"
#include "MsgID.h"
#include "MsgStruct.h"

#include <string.h>
#include <stdio.h>
#include <Windows.h>

#pragma warning(disable:4996)

static HANDLE com_handle = 0;
static const char* lua_src_buf = 0;
static const int   lua_src_buf_len = 0;

static char* lua_dst_buf = 0;
static int   lua_dst_buf_len = 0;

static int   lua_share_send_len = 0;

static char _log_buf[1024] = {0};


extern int add_uart_log(int log_type, const char* data, int len);


#define CLINET_DEBUG_LOG(fmt, ...) { \
	memset(_log_buf, 0, sizeof(_log_buf)); \
	sprintf(_log_buf, "%s:%d fn:%s " fmt "\n", strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
	WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), _log_buf, strlen(_log_buf), NULL, NULL); \
}

static int ON_MODULE_MSG(CUartSendModule, MSG_ID_START_UART_SEND) {
	ST_START_UART_SEND* param = (ST_START_UART_SEND*)msg;
	com_handle = (HANDLE)param->ptr;
	return 0;
}

static int ON_MODULE_MSG(CUartSendModule, MSG_ID_STOP_UART_SEND) {
	com_handle = 0;
	return 0;
}

static int sub_do_uart_send(HANDLE com_handle, char* buf, int len) {
	OVERLAPPED osWriter = { 0 };  // overlapped structure for write operations  
	osWriter.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (osWriter.hEvent == NULL) {
		return -2;// "Create writer event failed!";
	}

	BOOL fWaitingForWrite = FALSE;
	while (1) {
		if (!fWaitingForWrite) {
			DWORD factdata = 0;
			BOOL isSuccess = WriteFile(com_handle, buf, len, &factdata, &osWriter); //If the function succeeds, the return value is nonzero (TRUE).
			if (!isSuccess) {
				int wError = GetLastError();
				if (wError == ERROR_INVALID_HANDLE) {
					return -3;// "ERROR_INVALID_HANDLE";
				}
				//				ASSERT(wError == ERROR_IO_PENDING);
				fWaitingForWrite = TRUE;
			}
			else {
				//do nothing temporarily  
				fWaitingForWrite = FALSE;
			}
		}
		/*wait for write pending operations to complete*/
		if (fWaitingForWrite) {
			DWORD wRes = WaitForSingleObject(osWriter.hEvent, 500); //If the function succeeds, the return value indicates the event that caused the function to return
			switch (wRes) {
			case WAIT_OBJECT_0: //The state of the specified object is signaled. 
				add_uart_log(LOG_TYPE_UART_SEND_DONE, buf, len);
				return 0;
			default:
				break;
			}
		}
	}
	return 0;
}

static int ON_MODULE_MSG(CUartSendModule, MSG_ID_UART_SEND_REQ) {
	ST_UART_SEND_REQ* param = (ST_UART_SEND_REQ*)msg;
	if (NULL == com_handle) {
		//TODO
		return -1;// "Please Open the Comm first!";
	}
	char* buf = param->send_data;
	int len = param->send_data_len;

	if (UART_SEND_REQ_FRAME == param->req_type) {
		len += 4;
		buf = malloc(len);
		buf[0] = 0x87;
		buf[1] = 0x9E;
		memcpy(&buf[2], param->send_data, param->send_data_len);
		buf[2 + param->send_data_len] = 0x88;
		buf[3 + param->send_data_len] = 0x66;
	}

	sub_do_uart_send(com_handle, buf, len);
	return 0;
}

static int reg_msgid_func(CModule* thes) {
	REG_MODULE_MSG_FUNC(CUartSendModule, thes, MSG_ID_START_UART_SEND);
	REG_MODULE_MSG_FUNC(CUartSendModule, thes, MSG_ID_STOP_UART_SEND);
	REG_MODULE_MSG_FUNC(CUartSendModule, thes, MSG_ID_UART_SEND_REQ);
    return 0;
}

int construct_uart_send_module(CUartSendModule* thes, const char* module_name) {
	construct_module(&thes->parent, module_name);
	reg_msgid_func(AS_MODULE(thes));
	AS_MODULE(thes)->run(AS_MODULE(thes), USE_DEFAULT_MODULE_ENTRY);
	return 0;
}

